﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using MahApps.Metro.Ext.Controls;
using System.Windows.Threading;
using MahApps.Metro.Ext.Common;
using Microsoft.Practices.Prism.ViewModel;
using System.ComponentModel;

namespace M2Ext.Demo
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : CustomMetroWindow
    {
        public MainWindow()
        {
            InitializeComponent();

            this.currentTheme = MahApps.Metro.Theme.Dark;
            this.currentAccent = MahApps.Metro.ThemeManager.DefaultAccents.First(x => x.Name == "Green");

            //var t = new DispatcherTimer(TimeSpan.FromSeconds(2), DispatcherPriority.Normal, Tick, this.Dispatcher);

            this.DataContext = new MainWindowViewModel();
        }

        private int i = 0;
        private bool aa = true;

        void Tick(object sender, EventArgs e)
        {
            int j = i % 2, k = i % 3;

            this.indicator.IsBusy = j == 0;
            if(this.indicator.IsBusy)
            {
                this.indicator.ShowProgress = aa;
                this.indicator.Progress = 1.0 / i;
                aa = !aa;
                this.indicator.BusyMessage = "加载中..." + i;
            }
            
            App.Current.Resources[StyleConst.BusyIndicatorTypeKey] = k == 0 ? BusyIndicatorType.Ring : (k == 1 ? BusyIndicatorType.Line : BusyIndicatorType.Bar);

            this.currentTheme = j == 0 ? MahApps.Metro.Theme.Dark : MahApps.Metro.Theme.Light;
            this.currentAccent = k == 0 ? MahApps.Metro.ThemeManager.DefaultAccents.First(x => x.Name == "Red") : (k == 1 ? MahApps.Metro.ThemeManager.DefaultAccents.First(x => x.Name == "Purple") : MahApps.Metro.ThemeManager.DefaultAccents.First(x => x.Name == "Orange"));
            base.ChangeTheme(currentAccent, currentTheme);

            i++;
        }
    }

    public class MainWindowViewModel : NotificationObject, IDataErrorInfo
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                this.ValidateProperty("Name", value);
                this._name = value;
                RaisePropertyChanged(() => this.Name);
            }
        }

        private DateTime? _startTime;
        public DateTime? StartTime
        {
            get { return _startTime; }
            set
            {
                this.ValidateProperty("StartTime", value);
                this._startTime = value;
                RaisePropertyChanged(() => this.StartTime);
                RaisePropertyChanged(() => this.EndTime);
            }
        }

        private DateTime? _endTime;
        public DateTime? EndTime
        {
            get { return _endTime; }
            set
            {
                this.ValidateProperty("EndTime", value);
                this._endTime = value;
                RaisePropertyChanged(() => this.StartTime);
                RaisePropertyChanged(() => this.EndTime);
            }
        }

        private void ValidateProperty(string propertyName, object value)
        {

            if (propertyName == "Name")
            {
                this.RemoveError("Name");
                List<string> errors = new List<string>();

                var name = value as string;
                if (name == null)
                    errors.Add("Name is required.");
                else
                {
                    if (name.Length < 6)
                        errors.Add("Name length is no less than 6.");
                    if (name.Length > 10)
                        errors.Add("Name length is no more than 10.");
                }

                this.SetError(propertyName, errors);
            }
            else if (propertyName == "StartTime" || propertyName == "EndTime")
            {
                this.RemoveError("StartTime");
                this.RemoveError("EndTime");

                List<string> startTimeErrors = new List<string>();
                List<string> endTimeErrors = new List<string>();

                var dateTime = value as DateTime?;
                if (!dateTime.HasValue)
                {
                    var errors = propertyName == "StartTime" ? startTimeErrors : endTimeErrors;
                    errors.Add(string.Format("{0} is required.", propertyName));
                }

                DateTime? startTime;
                DateTime? endTime;
                if (propertyName == "StartTime")
                {
                    startTime = dateTime;
                    endTime = this._endTime;
                }
                else
                {
                    startTime = this._startTime;
                    endTime = dateTime;
                }

                if (startTime.HasValue && endTime.HasValue && startTime.Value > endTime.Value)
                {
                    startTimeErrors.Add("start time is smaller than to date");
                    endTimeErrors.Add("end time is greater than from date");
                }

                this.SetError("StartTime", startTimeErrors);
                this.SetError("EndTime", endTimeErrors);
            }
        }

        #region IDataErrorInfo Members

        protected void RaiseErrorsChanged(string propertyName)
        {
            this.OnErrorsChanged(new DataErrorsChangedEventArgs(propertyName));
        }

        protected virtual void OnErrorsChanged(DataErrorsChangedEventArgs e)
        {
            var handler = this.ErrorsChanged;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        private ErrorsContainer<string> errorsContainer;
        protected event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

        protected ErrorsContainer<string> ErrorsContainer
        {
            get
            {
                if (this.errorsContainer == null)
                {
                    this.errorsContainer =
                        new ErrorsContainer<string>(pn => this.RaiseErrorsChanged(pn));
                }

                return this.errorsContainer;
            }
        }

        public void SetError(string propertyName, List<string> errors)
        {
            this.ErrorsContainer.SetErrors(propertyName, errors);
        }

        public void RemoveError(string propertyName)
        {
            this.ErrorsContainer.ClearErrors(propertyName);
        }

        public bool HasErrors
        {
            get { return this.ErrorsContainer.HasErrors; }
        }

        public string Error
        {
            get
            {
                if (HasErrors)
                {
                    return "Data is invalid.";
                }
                else
                {
                    return null;
                }
            }
        }

        public string this[string propertyName]
        {
            get
            {
                var errors = this.ErrorsContainer.GetErrors(propertyName);
                if (errors.Count() > 0)
                    return errors.First();

                return null;
            }
        }

        #endregion
    }

    public class DataErrorsChangedEventArgs : EventArgs
    {

        public DataErrorsChangedEventArgs(string propertyName)
        {
            // TODO: Complete member initialization
            this.PropertyName = propertyName;
        }

        public string PropertyName { get; set; }
    }
}
